package com.liuke.study.thread;

import java.awt.*;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * TODO
 *
 * @author wangjwy
 * @date 2019/9/23 15:54
 * @since 1.0.0
 */
public class TestProviderConsumer {

	public static void main(String[] args) {
		Store store = new Store();
		Provider provider = new Provider(store);
		Provider provider2 = new Provider(store);
		Consumer consumer = new Consumer(store);
		Consumer consumer2 = new Consumer(store);

		new Thread(provider).start();
		new Thread(consumer).start();
		new Thread(provider2).start();
		new Thread(consumer2).start();
	}

}


class Store {

	private Integer max = 10;

	/*
	// synchronized关键字实现
	private List<String> lists = new LinkedList<>();

	public void provide() throws Exception {
		synchronized (lists) {
			while (lists.size() == max) {
				lists.wait();
			}
			lists.add(Thread.currentThread().getName() + ":" + "append");
			System.out.println(Thread.currentThread().getName() + ": 产生了一个, size:" + lists.size());
			lists.notify();
		}
	}

	public void consume() throws Exception {
		synchronized (lists) {
			while (lists.size() == 0){
				lists.wait();
			}
			lists.remove(0);
			System.out.println(Thread.currentThread().getName() + ": 消费了一个, size:" + lists.size());
			lists.notify();
		}
	}
	*/

	/*
	// lock实现
	private List<String> lists = new LinkedList<>();
	private ReentrantLock lock = new ReentrantLock();
	private Condition empty = lock.newCondition();
	private Condition full = lock.newCondition();

	public void provide() throws Exception {
		try {
			lock.lock();
			while (lists.size() == max) {
				full.await();
			}
			lists.add(Thread.currentThread().getName() + ":" + "append");
			System.out.println(Thread.currentThread().getName() + ": 产生了一个, size:" + lists.size());
			empty.signal();
		} finally {
			lock.unlock();
		}
	}

	public void consume() throws Exception {
		try {
			lock.lock();
			while (lists.size() == 0){
				empty.await();
			}
			lists.remove(0);
			System.out.println(Thread.currentThread().getName() + ": 消费了一个, size:" + lists.size());
			full.signal();
		} finally {
			lock.unlock();
		}
	}
	*/

	private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(max);

	public void provide() throws Exception {
		queue.put(Thread.currentThread().getName() + ":" + "append");
		System.out.println(Thread.currentThread().getName() + ": 产生了一个, size:" + queue.size());
	}

	public void consume() throws Exception {
		queue.take();
		System.out.println(Thread.currentThread().getName() + ": 消费了一个, size:" + queue.size());
	}

}

class Provider implements Runnable {

	private Store store;

	public Provider(Store store) {
		this.store = store;
	}

	@Override
	public void run() {
		try {
			for (;;){
				store.provide();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class Consumer implements Runnable {

	private Store store;

	public Consumer(Store store) {
		this.store = store;
	}

	@Override
	public void run() {
		try {
			for (;;){
				store.consume();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}